#pragma ident "$Id XY. CAO. 2016-11-24 $"

//============================================================================
//
//  Copyright (c)
//
//  XY. CAO, Wuhan Uniersity, 2016
//
//  hold the raw type id from rinex: C1C, C1W, C2W, C5Q, C5X, ...
//  SJ. Zhang, Wuhan University, 2019.6.1
//
//============================================================================

#include "IFCBCorrection.hpp"

using namespace std;

namespace gpstk
{

      // Returns a string identifying this object.
   string IFCBCorrection::getClassName() const
   { return "IFCBCorrection"; }

   
      /* Returns a satTypeValueMap object, adding the new data generated
       *  when calling this object.
       *
       * @param time      Epoch corresponding to the data.
       * @param gData     Data object holding the data.
       */
   satTypeValueMap& IFCBCorrection::Process( const CommonTime& time,
                                                satTypeValueMap& gData )
      noexcept(false)
   {
	   try
	   {

		   SatIDSet satRejectedSet;

		   // Loop through all the satellites
		   satTypeValueMap::iterator it;
		   for (it = gData.begin(); it != gData.end(); ++it)
		   {
			   SatID sat = it->first;

			   if(sat.system == SatelliteSystem::GPS)
			   {
                   if(it->second.find(TypeID::GFIF)!=(*it).second.end())
                   {
				       // Second, find the IFCB(Not all)
				       double ifcb;
				       try
				       {

                           if(pIFCBStore==NULL)
                           {
                               ProcessingException e("mgexDCBStore is NULL");
                               cerr << e << endl;
                               exit(-1);
                           }

				           // For dual-frequency
				           SatIFCB satIFCB = (*pIFCBStore).getValue(sat, time);
                           YDSTime epoch(time);

                           it->second[TypeID::GFIF] = it->second[TypeID::GFIF] - satIFCB.ifcb;
				       }
				       catch(...)
				       {
				           continue;
				       }
                   }

                   // correct LC15 observations
                   if(it->second.find(TypeID::LC15)!=(*it).second.end())
                   {
				       // Second, find the IFCB(Not all)
				       double ifcb;
				       try
				       {

                           if(pIFCBStore==NULL)
                           {
                               ProcessingException e("mgexDCBStore is NULL");
                               cerr << e << endl;
                               exit(-1);
                           }

				           // For dual-frequency
				           SatIFCB satIFCB = (*pIFCBStore).getValue(sat, time);
                           YDSTime epoch(time);

                           it->second[TypeID::LC15] = it->second[TypeID::LC15] - satIFCB.ifcb;
				       }
				       catch(...)
				       {
				           continue;
				       }
                   }
			   }
  

		   }  // End of 'for (it = gData.begin(); it != gData.end(); ++it)'

		   // Let's remove satellites without all TypeID's
		   gData.removeSatID(satRejectedSet);

		   return gData;
	   }
	   catch(Exception& u)
	   {

		   // Throw an exception if something unexpected happens
		   ProcessingException e( getClassName() + ":"
			   + u.what() );

		   GPSTK_THROW(e);

	   }

   }  // End of method 'IFCBCorrection::Process()'

   void IFCBCorrection::Process(commonHeader& comHeader, gnssRinex& gData)
   {
           // set dcb file pointer from ggd;
        pIFCBStore = comHeader.pIFCBStore;
        Process(gData.header.epoch, gData.body);
   };

    /** Return a sourceRinex object, adding the new data generated
     *  when calling this object.
     *
     * @param gData     Data object holding the data.
     */
    void IFCBCorrection::Process(commonHeader& comHeader,sourceRinex& gData) 
    {
           // set dcb file pointer from ggd;
        pIFCBStore = comHeader.pIFCBStore;
        for( sourceDataMap::iterator sdmIt = gData.body.begin();
             sdmIt != gData.body.end();
             ++sdmIt )
        {
            Process( gData.header.epoch, sdmIt->second );
        }

    }  // End of method 'IFCBCorrection::Process()'


}  // End of namespace gpstk

